﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Transactions;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity;
using Microsoft.Practices.Unity;
using Vallejos.Datos.Factory;
using Vallejos.Datos.Servicios;
using Vallejos.Entidades.Interfaces;
using Vallejos.Entidades.ModeloDeDatos;
using Vallejos.Excepciones;

namespace Vallejos.Datos.Accesos
{
    public class AnalisisCrediticioDAL : IAnalisisCrediticio
    {
        private readonly DatabaseService _database;

        public AnalisisCrediticioDAL()
        {
            var container = new UnityContainer()
                .AddNewExtension<EnterpriseLibraryCoreExtension>();
            _database = container.Resolve<DatabaseService>();
        }


        public SolicitudDeAnalisisCrediticio GenerarSolicitudDeAnalisis(SolicitudDeAnalisisCrediticio solicitud)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    using (var command = _database.GetStoredProcCommand("GenerarSolicitudDeAnalisis"))
                    {
                        _database.AddOutParameter(command, "Id", DbType.Int32, Int32.MaxValue);

                        _database.AddInParameter(command, "Id_Beneficiario", DbType.Int32, solicitud.Beneficiario.Id);
                        _database.AddInParameter(command, "Monto", DbType.Decimal, solicitud.Monto);
                        _database.AddInParameter(command, "CantidadDeCuotas", DbType.Int32, solicitud.CantidadDeCuotas);
                        _database.AddInParameter(command, "CFT", DbType.Decimal, solicitud.CFT);
                        _database.AddInParameter(command, "TNA", DbType.Decimal, solicitud.TNA);
                        _database.AddInParameter(command, "Id_Producto", DbType.Int32, solicitud.Producto.Id);
                        _database.AddInParameter(command, "Id_TipoFinanciacion", DbType.Int32,
                                                 (int) solicitud.TipoFinanciacion.idTipo);

                        _database.ExecuteNonQuery(command);

                        solicitud.Id = Convert.ToInt32(_database.GetParameterValue(command, "Id"));

                        GuardarHistorialDeSolicitud(solicitud);

                        scope.Complete();
                    }
                }

            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }
            return solicitud;
        }

        public SolicitudDeAnalisisCrediticio CambiarEstadoDeSolicitud(SolicitudDeAnalisisCrediticio solicitud)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    using (var command = _database.GetStoredProcCommand("CambiarEstadoDeSolicitudDeAnalisis"))
                    {
                        _database.AddInParameter(command, "Id_SolicitudDeAnalisis", DbType.Int32, solicitud.Id);
                        _database.AddInParameter(command, "Id_Estado", DbType.Int32, (int) solicitud.Estado.idEstado);

                        _database.ExecuteNonQuery(command);

                        GuardarHistorialDeSolicitud(solicitud);
                        scope.Complete();
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }
            return solicitud;
        }

        public void AsignarAnalistaDeSolicitud(SolicitudDeAnalisisCrediticio solicitud)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    using (var command = _database.GetStoredProcCommand("AsignarAnalistaDeSolicitud"))
                    {
                        _database.AddInParameter(command, "Id_SolicitudDeAnalisis", DbType.Int32, solicitud.Id);
                        _database.AddInParameter(command, "Id_Analista", DbType.Int32, solicitud.Analista.Id);

                        _database.ExecuteNonQuery(command);

                        scope.Complete();
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }
        }

        private void GuardarHistorialDeSolicitud(SolicitudDeAnalisisCrediticio solicitud)
        {
            try
            {
                using (var command = _database.GetStoredProcCommand("GuardarHistorialDeSolicitudDeAnalisis"))
                {
                    _database.AddInParameter(command, "Id_SolicitudDeAnalisis", DbType.Int32, solicitud.Id);
                    _database.AddInParameter(command, "Id_Estado", DbType.Int32, (int)solicitud.Estado.idEstado);

                    _database.ExecuteNonQuery(command);
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }
        }

        public SolicitudDeAnalisisCrediticio LeerSolicitudDeAnalisisEnCurso(int idCliente)
        {
            SolicitudDeAnalisisCrediticio solicitud = null;

            var factory = new SolicitudFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerSolicitudDeAnalisisEnCurso"))
                {
                    _database.AddInParameter(command, "Id_Cliente", DbType.Int32, idCliente);

                    using (var reader = _database.ExecuteReader(command))
                        if (reader.Read())
                        {
                            solicitud = (SolicitudDeAnalisisCrediticio)factory.Crear(reader);
                            solicitud.Historial = LeerHistorialDeSolicitudDeAnalisis(solicitud.Id);
                        }
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return solicitud;
        }

        public SolicitudDeAnalisisCrediticio LeerSolicitudDeAnalisisAprobadaDeCliente(string CUIL)
        {
            SolicitudDeAnalisisCrediticio solicitud = null;

            var factory = new SolicitudFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerSolicitudDeAnalisisAprobadaDeCliente"))
                {
                    _database.AddInParameter(command, "CUIL_Cliente", DbType.String, CUIL);

                    using (var reader = _database.ExecuteReader(command))
                        if (reader.Read())
                        {
                            solicitud = (SolicitudDeAnalisisCrediticio)factory.Crear(reader);
                            solicitud.Historial = LeerHistorialDeSolicitudDeAnalisis(solicitud.Id);
                        }
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return solicitud;
        }

        public SolicitudDeAnalisisCrediticio LeerUltimaSolicitudDeAnalisisDenegada(int idCliente)
        {
            SolicitudDeAnalisisCrediticio solicitud = null;

            var factory = new SolicitudFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerUltimaSolicitudDeAnalisisDenegada"))
                {
                    _database.AddInParameter(command, "Id_Cliente", DbType.Int32, idCliente);

                    using (var reader = _database.ExecuteReader(command))
                        if (reader.Read())
                        {
                            solicitud = (SolicitudDeAnalisisCrediticio)factory.Crear(reader);
                            solicitud.Historial = LeerHistorialDeSolicitudDeAnalisis(solicitud.Id);
                        }
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return solicitud;
        }

        public List<HistorialDeAnalisis> LeerHistorialDeSolicitudDeAnalisis(int idSolicitud)
        {
            var historial = new List<HistorialDeAnalisis>();

            var factory = new HistorialDeAnalisisFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerHistorialDeSolicitudDeAnalisis"))
                {
                    _database.AddInParameter(command, "Id_SolicitudDeAnalisis", DbType.Int32, idSolicitud);

                    using (var reader = _database.ExecuteReader(command))
                        while (reader.Read())
                            historial.Add(factory.Crear(reader));
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return historial;
        }

        

        public List<Rubro> LeerRubros(int idLenguaje)
        {
            var rubros = new List<Rubro>();

            var factory = new RubroFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerRubros"))
                {
                    _database.AddInParameter(command, "Id_Lenguaje", DbType.Int32, idLenguaje);

                    using (var reader = _database.ExecuteReader(command))
                        while (reader.Read())
                            rubros.Add(factory.Crear(reader));
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return rubros;
        }

        public List<MotivoRezhazo> LeerMotivosDeRezhazo(int idLenguaje)
        {
            var motivos = new List<MotivoRezhazo>();

            var factory = new MotivoRezhazoFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerMotivosDeRezhazo"))
                {
                    _database.AddInParameter(command, "Id_Lenguaje", DbType.Int32, idLenguaje);

                    using (var reader = _database.ExecuteReader(command))
                        while (reader.Read())
                            motivos.Add(factory.Crear(reader));
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return motivos;
        }


        public List<SolicitudDeAnalisisCrediticio> LeerSolicitudDeAnalisisCrediticioPendientes(int idEmpleado)
        {
            var solicitudes = new List<SolicitudDeAnalisisCrediticio>();

            var factory = new SolicitudFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerSolicitudDeAnalisisCrediticioPendientes"))
                {
                    _database.AddInParameter(command, "Id_Analista", DbType.Int32, idEmpleado);

                    using (var reader = _database.ExecuteReader(command))
                        while (reader.Read())
                            solicitudes.Add((SolicitudDeAnalisisCrediticio)factory.Crear(reader));
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return solicitudes;
        }


        public List<EmpresaDeServicio> LeerEmpresasDeServicios()
        {
            var empresas = new List<EmpresaDeServicio>();

            var factory = new EmpresaDeServicioFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerEmpresasDeServicios"))
                {
                    using (var reader = _database.ExecuteReader(command))
                        while (reader.Read())
                            empresas.Add(factory.Crear(reader));
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return empresas;
        }
    }
}